package cn.wlh.learn.webmagic.selenium.discuz;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import cn.wlh.learn.webmagic.utils.ArrayUtils;
import cn.wlh.learn.webmagic.utils.SelectableUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.Cookie;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.processor.PageProcessor;
import us.codecraft.webmagic.selector.Html;
import us.codecraft.webmagic.selector.Selectable;

import java.sql.SQLException;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
 * 用Discuz搭建的论坛
 * 基础类。
 *
 * 该论坛中的url::
 * 以?mod=**  为列表标识。
 * <table border="1">
 *     <tr>
 *         <th>mod英文</th>
 *         <th>页面含义</th>
 *     </tr>
 *     <tr>
 *         <td> announcement </td>
 *         <td> 公告 </td>
 *     </tr>
 *     <tr>
 *         <td> space </td>
 *         <td> 个人空间 </td>
 *     </tr>
 *     <tr>
 *         <td> forumdisplay </td>
 *         <td> 论坛 </td>
 *     </tr>
 *     <tr>
 *         <td> viewthread </td>
 *         <td> 信息视图 </td>
 *     </tr>
 *     <tr>
 *         <td> redirect </td>
 *         <td> 重定向 </td>
 *     </tr>
 *   </table>
 *
 */
public abstract class AbstractDiscuzSelenium implements PageProcessor {
    private final static Log logger = LogFactory.get();
    /**
     * 论坛地址:: 列表页 匹配正则
     */
    public static final String REGEX_MOD_FORUMDISPLAY = "/forum.php\\?mod\\=forumdisplay&";
    /**
     * 论坛地址:: 列表页 匹配正则
     */
//    public static final String REGEX_VIEWTHREAD = ".*/forum.php\\?mod\\=viewthread&.*";
    /**
     * 过滤这个评论分页： ?mod=viewthread&tid=1389&extra=page%3D1&page=2
     */
    public static final String REGEX_VIEWTHREAD = ".*/forum.php\\?mod\\=viewthread&tid=\\d+&extra\\=[A-Za-z0-9%]+$"; //
    //

    static{
        // 注册驱动
        String driverPath = "D:/chromedriver.exe";
        System.setProperty("webdriver.chrome.driver",
                driverPath);
        logger.info("selenium driver Path is [{}]" ,driverPath );
    }

    protected Site site = Site
            .me()
            .setRetryTimes(3)
            .setSleepTime(10000)
            .setRetrySleepTime(10000)
            .setTimeOut(10000)
            .addHeader("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3")
            .addHeader("Connection", "keep-alive")
            .addHeader("X-Requested-With", "XMLHttpRequest")
            .addHeader("Content-Type",
                    "application/x-www-form-urlencoded;charset=utf-8")
            .addHeader(
                    "User-Agent",
                    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36");
    // 用来存储cookie信息
    private Set<Cookie> cookies = Collections.emptySet();
    /**
     * 登录地址
     */
    public final String index_url;


    public AbstractDiscuzSelenium(String index_url) {
        this(index_url,
                "873406903","873406903");
    }

    public AbstractDiscuzSelenium(String index_url, String useName , String pass) {
        this.index_url = index_url;
        this.login(useName,pass);
    }



    @Override
    public void process(Page page) {

        // 抓取规则
        Selectable url = page.getUrl();

        //
        Html html = page.getHtml();

        // 论坛地址:: 列表页
        if(url.regex(REGEX_MOD_FORUMDISPLAY).match()){
            logger.debug("进入论坛地址,列表页:: [{}]" , url );

//
//
//            xpath = html.xpath("//*[@id=\"threadlisttableid\"]");
//            links = xpath.links();
//            List<String> all2 = links.regex(URL_POST_REGEX).all();
//            page.addTargetRequests(all2);


            // 获得详情页。
            Selectable xpath = html.xpath("//*[@id=\"threadlisttableid\"]");
            Selectable links = xpath.links();
            List<String> all2 = links.regex(REGEX_VIEWTHREAD).all();
            page.addTargetRequests(all2);


            // 获得下一页
            Selectable autoPageButton = html.$("#autopbn","rel");
            String rel = autoPageButton.get();
            String autoPageButtonRequestString = this.getIndex_url() + "/" + rel;
            logger.debug("获得下一页,列表页地址为,放入待执行列表中，等待执行[{}] " , autoPageButtonRequestString );
            page.addTargetRequest(autoPageButtonRequestString);

        //
        }else if(url.regex(REGEX_VIEWTHREAD).match()){
            List<String> all = url.regex(REGEX_VIEWTHREAD).all();
            logger.debug("进入信息页面 , 交给具体的实现类处理:: [{}]" , url );
            viewthread(page);
        }else{
            logger.warn("其他不需要处理多余的页面 :: [{}]" , url );
        }

    }

    public abstract void viewthread(Page page) ;

    @Override
    public Site getSite() {
        StringBuilder sb = new StringBuilder();
        // 将获取到的cookie信息添加到webmagic中
        for (Cookie cookie : cookies) {
            String name = cookie.getName().toString();
            String value = cookie.getValue().toString();
            site.addCookie(name, value);
            sb.append(StrUtil.format("site.addCookie(\"{}\", \"{}\");\n",name,value));
        }
        logger.info("避免频繁登录,生成设置cookie的代码=[\n{}\n]",sb.toString());
        return site;
    }

    /**
     * 登录<br/>
     * 默认等待3s.
     */
    public void login(String useName , String pass) {
        int millis = 3000;
        login(useName,pass,millis,millis);
    }

    /**
     * 登录可控制时间 <br/>
     * 为了解决有些需要验证码,才能登录的问题 <br/>
     * @param useName
     * @param pass
     * @param inputMillis 等待输入的账号和密码的时间
     * @param cookiesMillis 等待获得cookies的时间
     */
    protected void login(String useName , String pass,int inputMillis , int cookiesMillis) {

        WebDriver driver = new ChromeDriver();
        try {
            driver.get(index_url);// 打开网址


            logger.debug("打开登录网址[{}],sleep {} ms , 防止页面未能及时加载出来而设置一段时间延迟", index_url,inputMillis);
            ThreadUtil.sleep(inputMillis);

            // 设置用户名密码
            driver.findElement(By.id("ls_username")).sendKeys(useName ); // 用户名
            driver.findElement(By.id("ls_password")).sendKeys(pass); // 密码
            // 模拟点击
            driver.findElement(By.xpath("//*[@id=\"lsform\"]/div/div/table/tbody/tr[2]/td[3]/button"))
                    .click(); // xpath语言：id为form-group-login的form下的button

            // 防止页面未能及时加载出来而设置一段时间延迟
            logger.debug("准备获得cookies,sleep {} ms , 防止页面未能及时加载出来而设置一段时间延迟",cookiesMillis);
            ThreadUtil.sleep(cookiesMillis );
            // 获取cookie信息
            WebDriver.Options manage = driver.manage();
            cookies = manage.getCookies();
            logger.debug("cookies内容[{}],关闭elenium驱动",cookies);
        } finally {
//            driver.close(); // 只是关闭,但是线程还开启。
            driver.quit();
        }
    }


    public String getIndex_url() {
        return index_url;
    }


    public static void main(String[] args) throws Exception {
        String url = "https://www.52lfy.com/forum.php?mod=viewthread&tid=1389&extra=page%3D1&page=2";
        // &extra=[A-Za-z0-9%]+
        String s = ReUtil.get(url, "forum.php", 0);
        System.out.println(s);
    }

}